<?php

namespace App\Kuafu\Order\Enum;

use App\Kuafu\Order\Exceptions\OrderException;

class OrderMerchantEnum
{
    // 顶部选择的时间选项
    const SHOW_TIME_TAB_TODAY     = 1; // 今天
    const SHOW_TIME_TAB_YESTERDAY = 2; // 昨天
    const SHOW_TIME_TAB_WEEK      = 3; // 本周
    const SHOW_TIME_TAB_MONTH     = 4; // 本月
    const SHOW_TIME_TAB_DEFINE    = 5; // 自定义

    const SHOW_TIME_TAB_TEXT = [
        self::SHOW_TIME_TAB_TODAY     => '今天',
        self::SHOW_TIME_TAB_YESTERDAY => '昨天',
        self::SHOW_TIME_TAB_WEEK      => '本周',
        self::SHOW_TIME_TAB_MONTH     => '本月',
        self::SHOW_TIME_TAB_DEFINE    => '自定义',
    ];

    // 对比的时间选项枚举
    const COMPARE_TIME_TAB_YESTERDAY     = 1; // 比昨天
    const COMPARE_TIME_TAB_PRE_YESTERDAY = 2; // 比前天
    const COMPARE_TIME_TAB_WEEK          = 3; // 比上周
    const COMPARE_TIME_TAB_DURATION_DAY  = 4; // 环比某段时间、某天
    const COMPARE_TIME_TAB_MONTH         = 5; // 比上月

    const COMPARE_TIME_TAB_TEXT = [
        self::COMPARE_TIME_TAB_YESTERDAY     => '昨天',
        self::COMPARE_TIME_TAB_PRE_YESTERDAY => '前天',
        self::COMPARE_TIME_TAB_WEEK          => "上周",
        self::COMPARE_TIME_TAB_DURATION_DAY  => '环比',
        self::COMPARE_TIME_TAB_MONTH         => '上月',
    ];

    // 统计类型
    const STAT_ORIGINAL_PRICE              = 1; // 订单原价
    const STAT_INCOME_PRICE                = 2; // 实收
    const STAT_ORDER_COUNT                 = 3; // 有效订单
    const STAT_DISCOUNT_PRICE              = 4; // 优惠金额
    const STAT_BEFORE_DISCOUNT_AVG_PRICE   = 5; // 折前单均
    const STAT_AFTER_DISCOUNT_AVG_PRICE    = 6; // 折后单均
    const STAT_INCOME_RATE                 = 7; // 到手率
    const STAT_PAY_PRICE                   = 8; // 实付
    const STAT_PLATFORM_PRICE              = 9; // 平台服务费
    const STAT_MERCHANT_ACT_PRICE          = 10; // 商家活动支出
    const STAT_MERCHANT_CHANNEL_PAY        = 11; // 渠道收入
    const STAT_MERCHANT_CHANNEL_COMMISSION = 12; // 渠道分佣
    const STAT_MERCHANT_WAI_MAI_SCORE_MT   = 13; // 美团外卖评分
    const STAT_MERCHANT_WAI_MAI_SCORE_ELM  = 14; // 饿了么外卖评分

    const STAT_TEXT = [
        self::STAT_ORIGINAL_PRICE              => '营业额',
        self::STAT_INCOME_PRICE                => '营业收入',
        self::STAT_ORDER_COUNT                 => '有效订单',
        self::STAT_DISCOUNT_PRICE              => '优惠金额',
        self::STAT_BEFORE_DISCOUNT_AVG_PRICE   => '折前单均',
        self::STAT_AFTER_DISCOUNT_AVG_PRICE    => '折后单均',
        self::STAT_INCOME_RATE                 => '到手率',
        self::STAT_PAY_PRICE                   => '顾客实付',
        self::STAT_MERCHANT_CHANNEL_PAY        => '渠道收入',
        self::STAT_MERCHANT_CHANNEL_COMMISSION => '渠道分佣',
        self::STAT_MERCHANT_WAI_MAI_SCORE_MT   => '美团评分',
        self::STAT_MERCHANT_WAI_MAI_SCORE_ELM  => '饿了么评分',
    ];

    // 统计数值的类型
    const NUM_TYPE_PRICE   = 1; // 金额分
    const NUM_TYPE_NUM     = 2; // 数量
    const NUM_TYPE_PERCENT = 3; // 百分比

    // 统计类型->对应的数值类型
    const STAT_TO_NUM = [
        self::STAT_ORIGINAL_PRICE              => self::NUM_TYPE_PRICE,
        self::STAT_INCOME_PRICE                => self::NUM_TYPE_PRICE,
        self::STAT_ORDER_COUNT                 => self::NUM_TYPE_NUM,
        self::STAT_DISCOUNT_PRICE              => self::NUM_TYPE_PRICE,
        self::STAT_BEFORE_DISCOUNT_AVG_PRICE   => self::NUM_TYPE_PRICE,
        self::STAT_AFTER_DISCOUNT_AVG_PRICE    => self::NUM_TYPE_PRICE,
        self::STAT_INCOME_RATE                 => self::NUM_TYPE_PERCENT,
        self::STAT_PAY_PRICE                   => self::NUM_TYPE_PRICE,
        self::STAT_MERCHANT_CHANNEL_PAY        => self::NUM_TYPE_PRICE,
        self::STAT_MERCHANT_CHANNEL_COMMISSION => self::NUM_TYPE_PRICE,
        self::STAT_MERCHANT_WAI_MAI_SCORE_MT   => self::NUM_TYPE_NUM,
        self::STAT_MERCHANT_WAI_MAI_SCORE_ELM  => self::NUM_TYPE_NUM,
    ];

    // 首页的营业概览统计项
    const STAT_INDEX_OVERVIEW = [
        OrderMerchantEnum::STAT_ORIGINAL_PRICE,
        OrderMerchantEnum::STAT_INCOME_PRICE,
        OrderMerchantEnum::STAT_ORDER_COUNT,
        OrderMerchantEnum::STAT_AFTER_DISCOUNT_AVG_PRICE,
    ];

    // 店内订单营业概览统计项
    const STAT_ORDER_IN_OVERVIEW = [
        OrderMerchantEnum::STAT_ORIGINAL_PRICE,
        OrderMerchantEnum::STAT_INCOME_PRICE,
        OrderMerchantEnum::STAT_DISCOUNT_PRICE,
        OrderMerchantEnum::STAT_ORDER_COUNT,
        OrderMerchantEnum::STAT_BEFORE_DISCOUNT_AVG_PRICE,
        OrderMerchantEnum::STAT_AFTER_DISCOUNT_AVG_PRICE,
    ];

    // 外卖订单营业概览统计项
    const STAT_ORDER_WAI_MAI_OVERVIEW = [
        OrderMerchantEnum::STAT_ORIGINAL_PRICE,
        OrderMerchantEnum::STAT_INCOME_PRICE,
        OrderMerchantEnum::STAT_PAY_PRICE,
        OrderMerchantEnum::STAT_ORDER_COUNT,
        OrderMerchantEnum::STAT_INCOME_RATE,
        OrderMerchantEnum::STAT_AFTER_DISCOUNT_AVG_PRICE,
        OrderMerchantEnum::STAT_MERCHANT_WAI_MAI_SCORE_MT,
        OrderMerchantEnum::STAT_MERCHANT_WAI_MAI_SCORE_ELM,
    ];

    const ORDER_TYPE_TOTAL          = -1; // 合计订单
    const ORDER_TYPE_IN             = 1; // 店内订单
    const ORDER_TYPE_WAI_MAI        = 2;  // 外卖订单
    const ORDER_TYPE_COUPON_PACKAGE = 3; // 券包订单
    const ORDER_TYPE_DISTRIBUTION   = 4; // 分销订单
    const ORDER_TYPE_WAIMAI_SCORE   = 5; // 外卖评分

    const ORDER_TYPE_TEXT = [
        self::ORDER_TYPE_TOTAL          => '所有订单',
        self::ORDER_TYPE_IN             => '店内订单',
        self::ORDER_TYPE_WAI_MAI        => '外卖订单',
        self::ORDER_TYPE_COUPON_PACKAGE => '券包订单',
        self::ORDER_TYPE_DISTRIBUTION   => '分销订单',
        self::ORDER_TYPE_WAIMAI_SCORE   => '外卖评分',
    ];

    const ORDER_TYPE_TIME_COLUMN = [
        self::ORDER_TYPE_IN             => 'completeTime',
        self::ORDER_TYPE_WAI_MAI        => 'createdAt',
        self::ORDER_TYPE_COUPON_PACKAGE => 'createdAt',
        self::ORDER_TYPE_DISTRIBUTION   => 'createdAt',
        self::ORDER_TYPE_WAIMAI_SCORE   => 'date',
    ];

    const CHART_INTERVAL = [
        self::SHOW_TIME_TAB_TODAY     => 3600,
        self::SHOW_TIME_TAB_YESTERDAY => 3600,
        self::SHOW_TIME_TAB_WEEK      => 86400,
        self::SHOW_TIME_TAB_MONTH     => 86400,
        self::SHOW_TIME_TAB_DEFINE    => 86400,
    ];

    // 不同时间选择，对应的折线图横坐标间隔
    public static function getChartInterval(int $showTimeTab, int $startTime, int $endTime): int
    {
        switch ($showTimeTab) {
            case self::SHOW_TIME_TAB_TODAY:
            case self::SHOW_TIME_TAB_YESTERDAY:
                return 3600;
            case self::SHOW_TIME_TAB_WEEK:
            case self::SHOW_TIME_TAB_MONTH:
                return 86400;
            case self::SHOW_TIME_TAB_DEFINE:
                if ($endTime - $startTime <= 86400) {
                    return 3600;
                } else {
                    return 86400;
                }
            default:
                return 86400;
        }
    }

    // 统计类型对应的，DB字段
    const STAT_DB_COLUMN = [
        self::ORDER_TYPE_IN => [
            self::STAT_ORIGINAL_PRICE            => 'originalPrice',
            self::STAT_INCOME_PRICE              => 'payPrice',
            self::STAT_ORDER_COUNT               => '有效订单',
            self::STAT_DISCOUNT_PRICE            => '优惠金额',
            self::STAT_BEFORE_DISCOUNT_AVG_PRICE => '折前单均',
            self::STAT_AFTER_DISCOUNT_AVG_PRICE  => '折后单均',
            self::STAT_INCOME_RATE               => '到手率',
            self::STAT_PAY_PRICE                 => '顾客实付',
        ],
    ];

    // 菜品销售统计，排序字段
    const PRODUCT_SALES_COLUMN_SALES_NUM = 1; // 销量
    const PRODUCT_SALES_COLUMN_INCOMES   = 2; // 实收

    const PRODUCT_SALES_COLUMN = [
        self::PRODUCT_SALES_COLUMN_SALES_NUM => 'salesNum',
        self::PRODUCT_SALES_COLUMN_INCOMES   => 'incomes',
    ];

    // 菜品销售统计，分组字段
    const PRODUCT_SALES_GROUP_BY_PRODUCT  = 1; // 按菜品分组
    const PRODUCT_SALES_GROUP_BY_CATEGORY = 2; // 按分类分组

    const PRODUCT_SALES_GROUP_BY_ENUM = [
        self::PRODUCT_SALES_GROUP_BY_PRODUCT  => '',
        self::PRODUCT_SALES_GROUP_BY_CATEGORY => '',
    ];

    // 外卖评分弹窗报警阈值
    const WAIMAI_SCORE_ALERT_THRESHOLD = 4.8;

    /**
     * 查询的时间选项
     * @var int
     */
    private int $showTimeTab;

    /**
     * 查询的自定义开始时间戳
     * @var int
     */
    private int $showStartAt;

    /**
     * 查询的结束时间戳
     * @var int
     */
    private int $showEndAt;

    private int $compareTimeTab;
    private int $compareStartAt, $compareEndAt;

    private function __construct()
    {
    }

    private static $ins;

    public static function getIns()
    {
        if (self::$ins instanceof self) {
            return self::$ins;
        }

        return self::$ins = new self;
    }

    public function setShowTimeTab(int $showTimeTab, int $defineStartAt = 0, int $defineEndAt = 0)
    {
        $this->showTimeTab = $showTimeTab;
        $this->showStartAt = $defineStartAt;
        $this->showEndAt   = $defineEndAt;

        // 自定义时间选项的处理
        if ($this->showTimeTab == self::SHOW_TIME_TAB_DEFINE) {

            if (!$this->showEndAt) {
                throw new OrderException(OrderCodeEnum::ERR_DEFINE_TIME_NULL);
            }

            if ($this->showEndAt < $this->showStartAt) {
                throw new OrderException(OrderCodeEnum::ERR_ORDER_TIME);
            }
        }

        return $this;
    }

    public function setCompareTimeTab(int $compareTimeTab, int $defineStartAt = 0, int $defineEndAt = 0)
    {
        $this->compareTimeTab = $compareTimeTab;
        $this->compareStartAt = $defineStartAt;
        $this->compareEndAt   = $defineEndAt;

        // 自定义时间选项的处理
        if ($this->compareTimeTab == self::COMPARE_TIME_TAB_DURATION_DAY) {

            if (!$this->compareEndAt) {
                throw new OrderException(OrderCodeEnum::ERR_DEFINE_TIME_NULL);
            }

            if ($this->compareEndAt < $this->compareStartAt) {
                throw new OrderException(OrderCodeEnum::ERR_ORDER_TIME);
            }
        }

        return $this;
    }


    /**
     * 查询时间枚举，关联的时间戳
     *
     * 1.选择的名称
     * 2.选择的时间戳范围
     *
     * @return array
     */
    public function getShowTimeTab(): array
    {
        return [
                self::SHOW_TIME_TAB_TODAY     => [
                    '今天',
                    $todayStart = strtotime(date('Ymd')),
                    $todayEnd = $todayStart + 86400 - 1,
                    $todayEnd,
                ],
                self::SHOW_TIME_TAB_YESTERDAY => [
                    '昨天',
                    $todayStart - 86400,
                    $ori = $todayEnd - 86400,
                    $ori,
                ],
                self::SHOW_TIME_TAB_WEEK      => [
                    '本周',
                    strtotime(date('Ymd', strtotime('this week'))),
//                    $ori = strtotime(date('Ymd')) + 86400 - 1, // 今天23:59:59
                    $ori = strtotime(date('Y-m-d', strtotime("this week Sunday", time()))) + 86400 - 1, // 周日23:59:59
                    $ori,
                ],
                self::SHOW_TIME_TAB_MONTH     => [
                    '本月',
                    strtotime(date('Ym01')),
//                    $ori = strtotime(date('Ymd')) + 86400 - 1, // 今天23:59:59
                    $ori = mktime(23, 59, 59, date('m'), date('t'), date('Y')), // 月末23:59:59
                    $ori,
                ],
                self::SHOW_TIME_TAB_DEFINE    => [
//                    '环比：' . date('Ymd', $this->showStartAt) . '-' . date('Ymd', $this->showEndAt),
                    '当前',
                    $this->showStartAt,
                    $ori = $this->showEndAt,
                    $ori,
                ],
            ][$this->showTimeTab] ?? [];
    }

    /**
     * 对比时间枚举，关联的时间戳
     * @return array [0标题 1开始时间 2同时段对比的结束时间 3非同时段对比的结束时间]
     */
    public function getCompareTimeTab(): array
    {
        switch ($this->compareTimeTab) {
            case self::COMPARE_TIME_TAB_YESTERDAY:
                $s = [
                    '昨天',
                    $start = strtotime(date('Ymd')) - 86400,
                    $this->doSameEndTime($ori = $start + 86400 - 1),
                    $ori,
                ];
                break;

            case self::COMPARE_TIME_TAB_PRE_YESTERDAY:
                $s = [
                    '前天',
                    $start = strtotime(date('Ymd')) - 86400 * 2,
                    $this->doSameEndTime($ori = $start + 86400 - 1),
                    $ori,
                ];
                break;
            case self::COMPARE_TIME_TAB_WEEK:

                if ($this->showTimeTab == self::SHOW_TIME_TAB_YESTERDAY) {

                    // 『昨天』的『比上周』 - 上周的昨天一整天
                    $s = [
                        '上周',
                        $start = strtotime(date('Ymd')) - 86400 * 8,
                        $this->doSameEndTime($ori = $start + 86400 - 1),
                        $ori,
                    ];
                } elseif ($this->showTimeTab == self::SHOW_TIME_TAB_TODAY) {

                    // 『今天』的『比上周』 - 上周今天的同时段
                    $s = [
                        '上周',
                        $start = strtotime(date('Ymd')) - 86400 * 7,
                        $this->doSameEndTime($ori = $start + 86400 - 1),
                        $ori,
                    ];
                } else {

                    // 同时段累计的『比上周』
                    $s = [
                        '上周',
                        strtotime(date('Ymd', strtotime('this week'))) - 86400 * 7,
                        $this->doSameEndTime($ori = strtotime(date('Ymd')) - 6 * 86400 - 1),
                        strtotime(date('Ymd', strtotime('this week'))) - 1,
                    ];
                }

                break;
            case self::COMPARE_TIME_TAB_DURATION_DAY:
                $s = [
                    '上周期（' . date('m/d', $this->compareStartAt) . '-' . date('m/d', $this->compareEndAt) . '）',
                    $this->compareStartAt,
                    $this->doSameEndTime($this->compareEndAt),
                    $this->compareEndAt,
                ];
                break;

            case  self::COMPARE_TIME_TAB_MONTH:
                $s = [
                    '上月',
                    mktime(0, 0, 0, date('m') - 1, 1, date('Y')),
                    $this->doSameEndTime($this->last_month_today()),
                    strtotime(date('Ym01')) - 1,
                ];
                break;
            default:
                $s = [];
                break;
        }

        return $s;
    }

    /**
     * 店内外订单明细，根据『查询时间』映射对比的『时间段』
     * @return array [0标题 1开始时间 2同时段对比的结束时间 4非同时段对比的结束时间]
     * @throws OrderException
     */
    public function getOrderOverviewCompareInfo(): array
    {
        switch ($this->showTimeTab) {
            case self::SHOW_TIME_TAB_TODAY:
                $s = [
                    [
                        '昨天',
                        $yesterdayStart = strtotime(date('Ymd')) - 86400,
                        $this->doSameEndTime($ori = $yesterdayStart + 86400 - 1),
                        $ori,
                    ],
                    [
                        '上周',
                        $start = strtotime(date('Ymd')) - 86400 * 7,
                        $this->doSameEndTime($ori = $start + 86400 - 1),
                        $ori,
                    ],
                ];
                break;
            case self::SHOW_TIME_TAB_YESTERDAY:
                $s = [
                    [
                        '前天',
                        $start = strtotime(date('Ymd')) - 86400 * 2,
                        $this->doSameEndTime($ori = $start + 86400 - 1),
                        $ori,
                    ],
                    [
                        '上周',
                        $start = strtotime(date('Ymd')) - 86400 * 8,
                        $this->doSameEndTime($ori = $start + 86400 - 1),
                        $ori,
                    ],
                ];
                break;
            case self::SHOW_TIME_TAB_WEEK:

                $s = [
                    [
                        '上周',
                        strtotime(date('Ymd', strtotime('this week'))) - 86400 * 7,
                        $this->doSameEndTime($ori = strtotime(date('Ymd')) - 6 * 86400 - 1),
                        strtotime(date('Ymd', strtotime('this week'))) - 1,
                    ],
                ];
                break;
            case self::SHOW_TIME_TAB_MONTH:

                $s = [
                    [
                        '上月',
                        mktime(0, 0, 0, date('m') - 1, 1, date('Y')),
                        $this->doSameEndTime($ori = $this->last_month_today()),
                        strtotime(date('Ym01')) - 1,
                    ],
                ];
                break;
            case self::SHOW_TIME_TAB_DEFINE:
                $diffDay = (int)ceil(($this->showEndAt - $this->showStartAt) / 86400);

                $compareStart = $this->showStartAt - $diffDay * 86400;
                $compareEnd   = $this->showEndAt - $diffDay * 86400;

                $s = [
                    [
                        "前{$diffDay}天",
                        (int)$compareStart,
                        $this->doSameEndTime($ori = $compareEnd),
                        $ori,
                    ]
                ];

                break;
            default:
                throw new OrderException(OrderCodeEnum::ERR_SHOW_TIME_TAB);
        }

        return $s;
    }

    // 上个月今天的结束时间戳
    private function last_month_today()
    {
        $time = time();

        $last_month_time = mktime(date("G", $time), date("i", $time),
            date("s", $time), date("n", $time), 0, date("Y", $time));
        $last_month_t    = date("t", $last_month_time);

        if ($last_month_t < date("j", $time)) {
            return strtotime(date("Y-m-t 23:59:59", $last_month_time));
        }

        return strtotime(date(date("Y-m", $last_month_time) . "-d 23:59:59", $time));
    }

    /**
     * 处理『同时段累计』
     * @param int $endTime
     * @return false|int
     */
    private function doSameEndTime(int $endTime)
    {
        // 默认用结束时间的 时分秒
        $h = date('H', $endTime);
        $i = date('i', $endTime);
        $s = date('s', $endTime);
        $y = date('Y', $endTime);
        $m = date('m', $endTime);
        $d = date('d', $endTime);

        if ($this->showTimeTab == self::SHOW_TIME_TAB_YESTERDAY) {
            return mktime($h, $i, $s, $m, $d, $y);
        }

        if ($this->showTimeTab == self::SHOW_TIME_TAB_DEFINE) {
            if ($this->showEndAt <= time()) {
                return mktime($h, $i, $s, $m, $d, $y);
            }
        }

        if ($this->showTimeTab == self::SHOW_TIME_TAB_MONTH || (isset($this->compareTimeTab) && $this->compareTimeTab == self::COMPARE_TIME_TAB_MONTH)) {

            // 举例：3.29 10点，查询『比上月』。取的是2.28 23:59:59
            if ($d < date('d')) {
                return mktime(23, 59, 59, $m, $d, $y);
            }
        }

        // 触发同时段累计
        $now = time();
        $h   = date('H', $now);
        $i   = date('i', $now);
        $s   = date('s', $now);

        return mktime($h, $i, $s, $m, $d, $y);
    }
}

